
/**
 * @class ExtMVC.view.HasManyEditorGridPanel
 * @extends Ext.grid.EditorGridPanel
 * Provides some sensible defaults for a HasMany editor grid.  For example, given the following models:
 * ExtMVC.Model.define("MyApp.models.User", {
 *   ...
 *   hasMany: "Post"
 * });
 *
 * ExtMVC.Model.define("MyApp.models.Post", {
 *   ...
 *   belongsTo: "User"
 * });
 *
 * Inside the edit User view, if we wanted to be able to quickly edit any of that User's Posts, we can insert
 * a HasManyEditorGridPanel like this:
 *
 * items: [
 *   {
 *     xtype:       'hasmany_editorgrid',
 *     modelObj:    userObj,
 *     association: userObj.posts,
 *     columns:     [... set up editor columns as per a normal EditorGridPanel]
 *   }
 * ]
 *
 * In the example above, userObj refers to the loaded User instance tied to the edit form.  The HasMany editor grid
 * automatically listens to afteredit events and saves the HasMany model (Post in this case).
 */
ExtMVC.view.HasManyEditorGridPanel = Ext.extend(Ext.grid.EditorGridPanel, {

			initComponent	: function() {
				Ext.applyIf(this, {
							autoScroll	: true,
							store		: this.association.findAll(),
							viewConfig	: {
								forceFit	: true
							}
						});

				if (this.hasTopToolbar) {
					this.addTopToolbar();
				}

				ExtMVC.view.HasManyEditorGridPanel.superclass.initComponent
						.apply(this, arguments);

				/**
				 * Set up listening on the afteredit event.  Simply saves the model instance
				 */
				this.on('afteredit', function(args) {
							args.record.save({
										success	: function() {
											args.record.commit();
										}
									});
						}, this);

				/**
				 * Set up listening to selection change to activate the Remove button
				 */
				this.getSelectionModel().on('selectionchange',
						function(selModel, selection) {
							if (this.deleteButton) {
								this.deleteButton.enable();
							};
						}, this
				);
			},

			/**
			 * @property hasTopToolbar
			 * @type Boolean
			 * True to automatically show a toolbar at the top of the grid with Add and Delete buttons (defaults to true)
			 */
			hasTopToolbar	: true,

			/**
			 * @property hasNewButton
			 * @type Boolean
			 * True to add a 'New' button to the top toolbar if the top toolbar is present (defaults to true)
			 */
			hasNewButton	: true,

			/**
			 * @property hasDeleteButton
			 * @type Boolean
			 * True to add a 'Delete' button to the top toolbar if the top toolbar is present (defaults to true)
			 */
			hasDeleteButton	: true,

			/**
			 * Private.
			 * Creates a top toolbar and applies it to 'this'.  Should only be called from inside initComponent
			 */
			addTopToolbar	: function(paramName) {
				var items = [];

				if (this.hasNewButton) {
					this.newButton = new Ext.Toolbar.Button({
								iconCls	: 'add',
								text	: 'Add',
								scope	: this,
								handler	: this.onAdd
							});

					items.push(this.newButton);
					items.push('-');
				};

				if (this.hasDeleteButton) {
					this.deleteButton = new Ext.Toolbar.Button({
								text		: 'Remove selected',
								disabled	: true,
								iconCls		: 'delete',
								scope		: this,
								handler		: this.onDelete
							});

					items.push(this.deleteButton);
				};

				Ext.applyIf(this, {
							tbar	: items
						});
			},

			/**
			 * @property windowConfig
			 * @type Object
			 * Config object passed when creating the New Association window.  Override this to customise
			 * the window that appears
			 */
			windowConfig	: {},

			/**
			 * Called when the Add button is clicked on the top toolbar
			 */
			onAdd			: function(btn) {
				if (!this.addWindow) {
					this.addWindow = new Ext.Window(Ext.applyIf(
									this.windowConfig, {
										title		: 'New',
										layout		: 'fit',
										modal		: true,
										height		: 300,
										width		: 400,
										items		: [this.form],
										closeAction	: 'hide',
										buttons		: [{
													text	: 'Save',
													iconCls	: 'save',
													scope	: this,
													handler	: this.onSaveNew
												}, {
													text	: 'Cancel',
													iconCls	: 'cancel',
													scope	: this,
													handler	: this.onCancelNew
												}]
									}
							)
					);
				}

				this.addWindow.show();
			},

			/**
			 * Called when a row is selected and the delete button is clicked
			 */
			onDelete		: function(btn) {
				var record = this.getSelectionModel().selection.record;

				if (record) {
					record.destroy({
								scope	: this,
								success	: function() {
									this.store.reload();
								},
								failure	: function() {
									Ext.Msg.alert('Delete failed',
											"Something went wrong while trying to delete - please try again"
									);
									this.store.reload();
								}
							});
				};

				this.deleteButton.disable();
			},

			/**
			 * Called when the user clicks the save button to create a new record
			 */
			onSaveNew		: function() {
				this.association.create(this.form.getForm().getValues(), {
							scope	: this,
							success	: function(modelObj, response) {
								this.store.reload();
								this.addWindow.hide();
							},
							failure	: function(modelObj, response) {
								this.form.getForm().clearInvalid();
								this.form.getForm().markInvalid(modelObj.errors
										.forForm());
							}
						});
			},

			/**
			 * Called when the user cancels adding a new association model
			 */
			onCancelNew		: function(paramName) {
				this.addWindow.hide();
			}
		});

Ext.reg('hasmany_editorgrid', ExtMVC.view.HasManyEditorGridPanel);
